﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Casamiel.API.Infrastructure.Filters;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MediatR;
using Casamiel.API.Application.Models.V2;
using Casamiel.Domain.Response;
using Casamiel.API.Infrastructure;
using Casamiel.Application.Commands;
using Casamiel.Domain.Request;
using Casamiel.API.Application.Commands;
using Casamiel.Domain.Entity;
using Casamiel.Common.Extensions;
using Casamiel.API.Application.Models;
using NLog;
using Newtonsoft.Json;
using Casamiel.API.Application.Models.Store;
using Casamiel.Application;
using Casamiel.API.Application.Services;
using System.Data;
using Newtonsoft.Json.Linq;
using Casamiel.Domain;
using Casamiel.Common;
using Casamiel.API.Application.Models.ICModels;
using Enyim.Caching;
using Microsoft.Extensions.Options;
using Casamiel.Application.Commands.Order;
using System.Globalization;
using Casamiel.Domain.Response.IC;

// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace Casamiel.API.Controllers.V3
{
    /// <summary>
    /// 
    /// </summary>
    [Produces("application/json")]
    [ApiVersion("3.0")]
    [Route("api/v{api-version:apiVersion}/Order")]
    //[TypeFilterAttribute(typeof(CheckTokenAttribute))]
    //[Authorize]
    [ApiController]
    public class OrderController : BaseController
    {
        /// <summary>
        /// The mediator.
        /// </summary>
        private readonly IMediator _mediator;
        private readonly NLog.ILogger logger = NLog.LogManager.GetLogger("OrderService");
        private readonly IIcApiService _icApiService;
        private readonly INetICService _netICService;
        private readonly IStoreService _storeService;
        private readonly ICasaMielSession _session;
        private readonly IPaymentService _paymentService;
        private readonly IMemberCardService _memberCardService;
        //private readonly IUserLogService _userLog;
        private readonly IMemcachedClient _memcachedClient;
        private readonly string _memcachedPrex;
        private readonly INoticeService _notice;
        private readonly IOrderService _order;
        private readonly string _apiname;
        /// <summary>
        /// Initializes a new instance of the <see cref="T:Casamiel.API.Controllers.V3.OrderController"/> class.
        /// </summary>
        /// <param name="notice"></param>
        /// <param name="mediator">Mediator.</param>
        /// <param name="iicApiService">Iic API service.</param>
        /// <param name="storeService">Store service.</param>
        /// <param name="casaMielSession">Casa miel session.</param>
        /// <param name="paymentService">Payment service.</param>
        /// <param name="memberCardService">Member card service.</param>
        /// <param name="memcachedClient"></param>
        /// <param name="optionsSnapshot"></param>
        /// <param name="order"></param>
        /// <param name="netICService"></param>
        /// 

        public OrderController(INoticeService notice, IMediator mediator, IIcApiService iicApiService, IStoreService storeService, ICasaMielSession casaMielSession, IPaymentService paymentService,
        IMemberCardService memberCardService, IMemcachedClient memcachedClient,
        IOptionsSnapshot<CasamielSettings> optionsSnapshot, IOrderService order, INetICService netICService)
        {
            if (optionsSnapshot == null) {
                throw new ArgumentNullException(nameof(optionsSnapshot));
            }
            _apiname = optionsSnapshot.Value.ApiName;
            _netICService = netICService;
            _mediator = mediator;
            _icApiService = iicApiService;
            _storeService = storeService;
            _session = casaMielSession;
            _paymentService = paymentService;
            _memberCardService = memberCardService;
            // _userLog = userLogService;
            _memcachedClient = memcachedClient;
            _memcachedPrex = optionsSnapshot.Value.MemcachedPre;
            _notice = notice;
            _order = order;
        }

        /// <summary>
        /// Mies the orders by app.
        /// </summary>
        /// <returns>The orders by app.</returns>
        /// <param name="req">Req.</param>
        /// <param name="token">Token.</param>
        [HttpPost]
        [Route("[action]")]
        public async Task<PagingResultRsp<List<CakeOrderGetListRsp>>> MyOrdersByAPP([FromBody] GetMyAllOrdersReq req, [FromHeader(Name = "u-token")] string token)
        {
            if (req == null) {
                throw new ArgumentNullException(nameof(req));
            }

            if (req.PageIndex <= 0) {
                req.PageIndex = 1;
            }
            if (req.PageSize <= 0) {
                req.PageSize = 20;
            }
            var mobile = MemberHelper.GetMobile(token);
            var command = new GetAllOrderListCommand(req.PageIndex, req.PageSize, req.Status, mobile);
            var result = await _mediator.Send(command).ConfigureAwait(false);
            return result;
        }
        /// <summary>
        /// 我的蛋糕商城订单列表(小程序用）
        /// </summary>
        /// <param name="req"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("[action]")]
        public async Task<PagingResultRsp<List<CakeOrderGetListRsp>>> MyOrders([FromBody] GetMyAllOrdersReq req, [FromHeader(Name = "u-token")] string token)
        {
            if (req == null) {
                throw new ArgumentNullException(nameof(req));
            }

            var mobile = MemberHelper.GetMobile(token);
            var cmd = new GetMyCakeOrderListCommand { Mobile = mobile, PageIndex = req.PageIndex, PageSize = req.PageSize, Status = req.Status };
            var result = await _mediator.Send(cmd).ConfigureAwait(false);
            return result;
        }


        /// <summary>
        ///我的会员券
        /// </summary>
        /// <param name="request"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("[action]")]
        public async Task<BaseResult<List<TicketItem>>> GetMyTickets(CakeBuyNowReq request, [FromHeader(Name = "u-token")] string token)
        {
            if (request is null) {
                throw new ArgumentNullException(nameof(request));
            }

            var mobile = MemberHelper.GetMobile(token);
            var entity = await _storeService.GetDetailV2ByReleationIdAsync<ICasaMielSession>(request.GoodsRelationId).ConfigureAwait(false);
            if (entity == null) {

                return new BaseResult<List<TicketItem>>(new List<TicketItem>(), 0, "");

            }
            var glist = new List<Domain.Request.Waimai.TakeOutOrderGoods> {
                new Domain.Request.Waimai.TakeOutOrderGoods {
                    GoodsBaseId = request.GoodsBaseId,
                    GoodsQuantity = request.Count,
                    GoodsRelationId = request.GoodsRelationId,
                    Price = entity.Price
                }
            };
            //Console.WriteLine(JsonConvert.SerializeObject(glist));
            var cmd = new GetTicketsStatusByOrderCommand(glist, request.StoreId, mobile, false, LoginInfo.Item3);
            return await _mediator.Send(cmd).ConfigureAwait(false);
        }



        /// <summary>
        /// 
        /// </summary>
        /// <param name="req"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("[action]")]
        public async Task<BaseResult<BuyNowRsp>> BuyNow([FromBody] CakeBuyNowReq req, [FromHeader(Name = "u-token")] string token)
        {
            if (req == null) {
                throw new ArgumentNullException(nameof(req));
            }

            logger.Trace($"BuyNow_v2:{JsonConvert.SerializeObject(req)}");
            var mobile = MemberHelper.GetMobile(token);

            var cmd = new BuyNowCommand(LoginInfo.Item3) {
                Count = req.Count,
                GoodsBaseId = req.GoodsBaseId,
                OrderType = req.BuyType,
                StoreRelationId = req.StoreRelationId,
                GoodsRelationId = req.GoodsRelationId,
                Storeid = req.StoreId,
                TakeTime = req.TakeTime
            };
            var result = await _mediator.Send(cmd).ConfigureAwait(false);
            return result;
        }
        /// <summary>
        /// 创建蛋糕商城订单( 代金券）
        /// </summary>
        /// <returns>The order.</returns>
        /// <param name="req">Req.</param>
        /// <param name="token">Token.</param>
        [HttpPost]
        [Route("[action]")]
        public async Task<BaseResult<PaymentRsp>> CreateOrderWithCashCoupon([FromBody] CakeOrderCreateV2Req req, [FromHeader(Name = "u-token")] string token)
        {
            if (req == null) {
                throw new ArgumentNullException(nameof(req));
            }

            logger.Trace($"CreateOrderWithCashCoupon:{JsonConvert.SerializeObject(req)}");
            var Loginfo = this.LoginInfo;
            var mobile = MemberHelper.GetMobile(token);
            var cmd = new CreateCakeOrderV2Command(LoginInfo.Item3) {
                CardNo = req.CardNO,
                StoreId = req.StoreId,
                ContactPhone = req.ContactPhone,
                Quantity = req.Quantity,
                CostPrice = req.CostPrice,
                Paymethod = req.PayMethod,
                Price = req.Price,
                Remark = req.Remark,
                Mobile = mobile,
                ConsigneeId = req.ConsigneeId,
                ContactName = req.ContactName,
                GoodsBaseId = req.GoodsBaseId,
                OrderType = req.OrderType,
                TakeTime = req.TakeTime,
                DiscountList = req.DiscountList,
                Id = req.Id,
                PayCardNO = req.PayCardNO,
                Source = Loginfo.Item2
            };
            var result = await _mediator.Send(cmd).ConfigureAwait(false);
            logger.Trace($"{JsonConvert.SerializeObject(result)}");
            if (result.Code == 0 && result.Content.Payed != true) {
                logger.Trace($"{JsonConvert.SerializeObject(result.Content)}");
                var array = result.Content.Paymentrequest.Split(',');
                var p_tradeno = $"C{DateTime.Now.ToString("yyMMddHHmmssfff", CultureInfo.CurrentCulture)}";
                var payment = new PaymentRecord {
                    ShopName = "",
                    OperationMethod = 2,
                    TradeNo = p_tradeno,
                    Amount = array[0].ToDouble(0),
                    PayMethod = req.PayMethod,
                    BillNO = result.Content.OrderCode,
                    IcTradeNO = array[1],
                    State = 0,
                    OperationState = 0,
                    CreateTime = DateTime.Now,
                    Mobile = mobile
                };

                string shopno;
                var shopinfo = await _paymentService.GetShopIdAndShopNameByBillNOAsync<ICasaMielSession>(result.Content.OrderCode).ConfigureAwait(false);
                payment.ShopName = shopinfo.Item2;
                payment.ShopId = shopinfo.Item1;

                var cachekey = string.Format(CultureInfo.CurrentCulture, Constant.SHOPNO, _memcachedPrex, payment.ShopId);
                shopno = await _memcachedClient.GetValueAsync<string>(cachekey).ConfigureAwait(false);
                if (string.IsNullOrEmpty(shopno)) {
                    var basedata = await _icApiService.BasedataQuery(new BasedataqueryReq { Datatype = 3, Datavalue = $"{payment.ShopId.Value}" }).ConfigureAwait(false);
                    if (basedata.code == 0) {
                        var d = JsonConvert.DeserializeObject<JArray>(basedata.content);
                        if (d.Count > 0) {
                            shopno = d[0]["no"].ToString();
                            await _memcachedClient.AddAsync(cachekey, shopno, 72000).ConfigureAwait(false);
                        }
                    }
                }
                payment.ShopNO = shopno;
                if (req.PayMethod == 4 && req.Id == 0) {
                    return new BaseResult<PaymentRsp>(null, 999, "出错了，请联系我们");
                }
                var command = new CreatePaymentRequestCommand(payment, req.Id, PaymentScenario.CakeStore);
                var result1 = await _mediator.Send(command).ConfigureAwait(false);


                var pay = new PaymentRsp {
                    OrderCode = result1.Ordercode,
                    Payed = result1.Payed,
                    Paymentrequest = result1.Paymentrequest,
                    PayMethod = result1.PayMethod.ToInt32(0)
                };
                return new BaseResult<PaymentRsp>(pay, 0, "");
            }


            return result;
        }

        /// <summary>
        ///  创建蛋糕商城订单
        /// </summary>
        /// <param name="req"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("[action]")]
        public async Task<BaseResult<PaymentRsp>> CreateOrder([FromBody] Cake_Order_CreateReq req, [FromHeader(Name = "u-token")] string token)
        {
            if (req == null) {
                throw new ArgumentNullException(nameof(req));
            }
            logger.Trace($"CreateOrder:{JsonConvert.SerializeObject(req)}");
            var Loginfo = this.LoginInfo;
            var mobile = MemberHelper.GetMobile(token);
            var cmd = new CreateCakeOrderCommand(Loginfo.Item3) {
                CardNo = req.CardNO,
                StoreId = req.StoreId,
                ContactPhone = req.ContactPhone,
                Quantity = req.Quantity,
                CostPrice = req.CostPrice,
                Paymethod = req.PayMethod,
                Price = req.Price,
                Remark = req.Remark,
                Mobile = mobile,
                ConsigneeId = req.ConsigneeId,
                ContactName = req.ContactName,
                GoodsBaseId = req.GoodsBaseId,
                OrderType = req.OrderType,
                TakeTime = req.TakeTime,
                DiscountCouponId = req.DiscountCouponId,
                DiscountCouponName = req.DiscountCouponName,
                DiscountCouponMoney = req.DiscountCouponMoney,
                Id = req.Id,
                PayCardNO = req.PayCardNO,
                InvoiceId = req.InvoiceId

            };
            var result = await _mediator.Send(cmd).ConfigureAwait(false);
            logger.Trace($"{JsonConvert.SerializeObject(result)}");
            if (result.Code == 0 && result.Content.Payed != true) {
                logger.Trace($"{JsonConvert.SerializeObject(result.Content)}");
                var array = result.Content.Paymentrequest.Split(',');
                var p_tradeno = $"C{DateTime.Now.ToString("yyMMddHHmmssfff", CultureInfo.CurrentCulture)}";
                var payment = new PaymentRecord {
                    ShopName = "",
                    OperationMethod = 2,
                    TradeNo = p_tradeno,
                    Amount = array[0].ToDouble(0),
                    PayMethod = req.PayMethod,
                    BillNO = result.Content.OrderCode,
                    IcTradeNO = array[1].ToString(CultureInfo.CurrentCulture),
                    State = 0,
                    OperationState = 0,
                    CreateTime = DateTime.Now,
                    Mobile = mobile
                };

                string shopno;
                var shopinfo = await _paymentService.GetShopIdAndShopNameByBillNOAsync<ICasaMielSession>(result.Content.OrderCode).ConfigureAwait(false);
                payment.ShopName = shopinfo.Item2;
                payment.ShopId = shopinfo.Item1;

                var cachekey = string.Format(CultureInfo.CurrentCulture, Constant.SHOPNO, _memcachedPrex, payment.ShopId);
                shopno = await _memcachedClient.GetValueAsync<string>(cachekey).ConfigureAwait(false);
                if (string.IsNullOrEmpty(shopno)) {
                    var basedata = await _icApiService.BasedataQuery(new BasedataqueryReq { Datatype = 3, Datavalue = $"{payment.ShopId.Value}" }).ConfigureAwait(false);
                    if (basedata.code == 0) {
                        var d = JsonConvert.DeserializeObject<JArray>(basedata.content);
                        if (d.Count > 0) {
                            shopno = d[0]["no"].ToString();
                            await _memcachedClient.AddAsync(cachekey, shopno, 72000).ConfigureAwait(false);
                        }
                    }
                }
                payment.ShopNO = shopno;
                if (req.PayMethod == 4 && req.Id == 0) {
                    return new BaseResult<PaymentRsp>(null, 999, "出错了，请联系我们");
                }
                var command = new CreatePaymentRequestCommand(payment, req.Id, PaymentScenario.CakeStore);
                var result1 = await _mediator.Send(command).ConfigureAwait(false);


                var pay = new PaymentRsp {
                    OrderCode = result1.Ordercode,
                    Payed = result1.Payed,
                    Paymentrequest = result1.Paymentrequest,
                    PayMethod = result1.PayMethod.ToInt32(0)
                };
                return new BaseResult<PaymentRsp>(pay, 0, "");
            }



            return result;
        }


        /// <summary>
        /// 
        ///获取蛋糕商城订单详情
        /// </summary>
        /// <returns>The detail.</returns>
        /// <param name="req">Req.</param>
        /// <param name="token">Token.</param>
        [HttpPost]
        [Route("[action]")]
        public async Task<BaseResult<CakeOrderBaseRsp>> GetDetail([FromBody] GetOrderDetailReq req, [FromHeader(Name = "u-token")] string token)
        {
            if (req == null) {
                throw new ArgumentNullException(nameof(req));
            }

            var mobile = MemberHelper.GetMobile(token);
            var cmd = new GetCakeOrderDetailCommand(req.OrderCode, mobile);
            var result = await _mediator.Send(cmd).ConfigureAwait(false);
            return result;
        }

        /// <summary>
        /// 获取蛋糕商城订单详情（代金券）
        /// </summary>
        /// <param name="req"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("[action]")]
        public async Task<BaseResult<Cake_OrderBaseV2Rsp>> GetDetailWithCashCoupon([FromBody] GetOrderDetailReq req, [FromHeader(Name = "u-token")] string token)
        {
            if (req == null) {
                throw new ArgumentNullException(nameof(req));
            }

            var mobile = MemberHelper.GetMobile(token);
            var cmd = new GetCakeOrderDetailV2Command(req.OrderCode, mobile);
            var result = await _mediator.Send(cmd).ConfigureAwait(false);
            return result;
        }
        /// <summary>
        /// Payment the specified data and token.
        /// </summary>
        /// <returns>The payment.</returns>
        /// <param name="data">Data.</param>
        /// <param name="token">Token.</param>
        [HttpPost]
        [Route("[action]")]
        public async Task<BaseResult<PaymentRsp>> Payment([FromBody] OrderPaymentReq data, [FromHeader(Name = "u-token")] string token)
        {
            if (data == null) {
                throw new ArgumentNullException(nameof(data));
            }

            var mobile = MemberHelper.GetMobile(token);
            var order = await _order.GetByOrderCodeAsync<ICasaMielSession>(data.OrderCode, mobile).ConfigureAwait(false);
            if (order == null) {
                return new BaseResult<PaymentRsp>(null, -23, "订单不存在");
            }
            var Storeinfo = await _storeService.GetByStoreIdAsync<ICasaMielSession>(order.StoreId).ConfigureAwait(false);
            if (Storeinfo == null) {
                return new BaseResult<PaymentRsp>(null, -23, "订单不存在");
            }
            if (order.OrderStatus != (int)OrderStatus.Create) {
                return new BaseResult<PaymentRsp>(null, -24, "订单状态不是待支付");
            }

            var payRsp = new PaymentRsp {
                OrderCode = order.OrderCode,
                PayMethod = data.PayMethod

            };
            if (order.OrderType == 1) {
                var orderTake = await _storeService.GetOrdeTakeByOrderCodeAsync<ICasaMielSession>(order.OrderBaseId).ConfigureAwait(false);
                if (orderTake == null) {
                    return new BaseResult<PaymentRsp>(null, -26, "提货单据出错");
                }
                if (order.CreateTime.DayOfYear == orderTake.TakeTime.DayOfYear) {
                    if (order.CreateTime.DayOfYear == DateTime.Now.DayOfYear) {
                        if (orderTake.TakeTime <= DateTime.Now) {
                            return new BaseResult<PaymentRsp>(null, -24, "订单状态不是待支付");
                        }
                    }
                } else {
                    if (orderTake.TakeTime.DayOfYear == DateTime.Now.DayOfYear || orderTake.TakeTime.DayOfYear < DateTime.Now.DayOfYear) {
                        return new BaseResult<PaymentRsp>(null, -24, "订单状态不是待支付");
                    }
                }
            }

            if (data.DiscountCouponId > 0) {

                var a = await _icApiService.Geticticket(new GetTicticketReq { Cardno = data.CardNO, Pagesize = 200, State = 2, Pageindex = 1 }).ConfigureAwait(false);
                if (a.code == 0) {
                    var list = JsonConvert.DeserializeObject<TicketItemRoot>(a.content);
                    var ticket = list.Tickets.Where(t => t.Ticketid == data.DiscountCouponId).SingleOrDefault();
                    if (ticket != null) {
                        data.DiscountCouponMoney = ticket.Je.ToDecimal(0);
                    } else {
                        return new BaseResult<PaymentRsp>(null, -23, "优惠券不可用");

                    }
                } else {
                    return new BaseResult<PaymentRsp>(null, -23, "优惠券不可用");
                }
            }
            var p_tradeno = $"C{DateTime.Now.ToString("yyMMddHHmmssfff", CultureInfo.CurrentCulture)}";
            // var amount = order.PayCashMoney;
            if (_apiname == "doncoApi") {
                var d = await _storeService.GetGoodsByOrderBaseIdAsync<ICasaMielSession>(order.OrderBaseId).ConfigureAwait(false);
                order.PayCashMoney = d.Sum(c => c.GoodsPrice * c.GoodsQuantity) - data.DiscountCouponMoney;

            }
            //var reorder = await _storeApiService.GetOrderByOrderCodeAsync(data.OrderCode, mobile);
            // var entity = await _storeService.GetByOrderCodeAsync<ICasaMielSession>(order.OrderCode, mobile);
            var payment = new PaymentRecord { OperationMethod = 2, TradeNo = p_tradeno, Amount = order.PayCashMoney.ToString(CultureInfo.CurrentCulture).ToDouble(0), PayMethod = data.PayMethod, BillNO = order.OrderCode, IcTradeNO = order.IcTradeNO, State = 0, OperationState = 0, CreateTime = DateTime.Now, Mobile = mobile };
            var shopno = "";
            var shopinfo = await _paymentService.GetShopIdAndShopNameByBillNOAsync<ICasaMielSession>(order.OrderCode).ConfigureAwait(false);
            payment.ShopName = shopinfo.Item2;
            payment.ShopId = shopinfo.Item1;

            var cachekey = string.Format(CultureInfo.CurrentCulture, Constant.SHOPNO, _memcachedPrex, payment.ShopId.Value);
            shopno = await _memcachedClient.GetValueAsync<string>(cachekey).ConfigureAwait(false);
            if (string.IsNullOrEmpty(shopno)) {
                var basedata = await _icApiService.BasedataQuery(new BasedataqueryReq { Datatype = 3, Datavalue = $"{payment.ShopId.Value}" }).ConfigureAwait(false);
                if (basedata.code == 0) {
                    var d = JsonConvert.DeserializeObject<JArray>(basedata.content);
                    if (d.Count > 0) {
                        shopno = d[0]["no"].ToString();
                        await _memcachedClient.AddAsync(cachekey, shopno, 72000).ConfigureAwait(false);
                    }
                }
            }
            payment.ShopNO = shopno;
            if (order.PayCashMoney < 0) {
                return new BaseResult<PaymentRsp>(null, 9999, "优惠券大于订单金额");
            }

            if (order.PayCashMoney == 0) {
                var pay = new IcConsumepayReq {
                    Shopid = Storeinfo.RelationId,
                    Tradeno = order.IcTradeNO,
                    Phoneno = mobile
                };
                pay.Paycontent = new List<IcConsumepayReq.PaycontentItem>();

                if (data.DiscountCouponId > 0) {
                    pay.Paycontent.Add(new IcConsumepayReq.PaycontentItem {
                        Paytype = "6",
                        Paymoney = data.DiscountCouponMoney.ToString(CultureInfo.CurrentCulture).ToDouble(0),
                        Paytradeno = $"t{DateTime.Now.ToString("yyMMddHHmmssffff", CultureInfo.CurrentCulture)}",
                        Payuser = $"{data.DiscountCouponId}"
                    });
                }


                var zmodel = await _icApiService.Icconsumepay(pay).ConfigureAwait(false);
                if (zmodel.code == 0) {
                    var jobject = JsonConvert.DeserializeObject<JObject>(zmodel.content);
                    if (jobject != null && jobject["invoiceqrcode"] != null) {
                        var invoiceUrl = jobject["invoiceqrcode"].ToString();
                        await _order.UpdateOrderInvoiceUrlByOrderCodeAsync<ICasaMielSession>(payment.BillNO, invoiceUrl).ConfigureAwait(false);
                    } else {
                        this.logger.Error($"Invoideurl:{zmodel.content}");
                    }

                    payment.PayMethod = data.PayMethod;
                    payment.PayTime = DateTime.Now;
                    payment.State = 1;
                    payment.OperationState = 1;
                    using (var uow = _session.UnitOfWork(IsolationLevel.Serializable)) {
                        order.OrderStatus = (int)OrderStatus.Paid;
                        order.PayTime = DateTime.Now;
                        await _order.OrderBaseUPdateAsync(order, uow).ConfigureAwait(true);
                        await _order.UpdateOrderTakeStatus(order.OrderBaseId, 0, "", uow).ConfigureAwait(true);
                        payment.State = 1;
                        payment.OperationState = 1;
                        payment.PayTime = DateTime.Now;
                        await _paymentService.AddAsync(payment, uow).ConfigureAwait(true);
                        var noticEntity = new NoticeBaseEntity() {
                            RemindTime = DateTime.Now.AddMinutes(-3),
                            CreateTime = DateTime.Now,
                            RelationId = order.OrderBaseId,
                            StoreId = order.StoreId,
                            NoticeType = 0
                        };
                        await _notice.AddAsync(noticEntity, uow).ConfigureAwait(true);

                    }
                    // return new JsonResult(new { code = 0, content = new { paymentrequest = "", ordercode = order.OrderCode, payMethod = payment.PayMethod.ToString(), payed = true } });
                    payRsp.Payed = true;

                    return new BaseResult<PaymentRsp>(payRsp, 0, "");
                }
                return new BaseResult<PaymentRsp>(null, zmodel.code, zmodel.msg);
            }

            switch (data.PayMethod) {
                case (int)PayMethod.Card:


                    if (string.IsNullOrEmpty(data.PayCardNO)) {
                        return new BaseResult<PaymentRsp>(null, 999, "卡号不能为空");
                    }
                    var cardinfo = await _memberCardService.FindAsync<ICasaMielSession>(data.PayCardNO, mobile).ConfigureAwait(false);
                    if (cardinfo == null) {
                        return new BaseResult<PaymentRsp>(null, 999, "卡号有误");
                    }

                    var pay = new IcConsumepayReq {
                        Cardno = data.PayCardNO,
                        Shopid = Storeinfo.RelationId,
                        Tradeno = order.IcTradeNO,
                        Createinvoice = true
                    };
                    pay.Paycontent = new List<IcConsumepayReq.PaycontentItem>
                    {
                        new IcConsumepayReq.PaycontentItem
                        {
                            Paytype = "3",
                            Paymoney = order.PayCashMoney.ToString(CultureInfo.CurrentCulture).ToDouble(0),
                            Paytradeno = $"c{DateTime.Now.ToString("yyMMddHHmmssffff", CultureInfo.CurrentCulture)}"
                        }
                    };
                    if (data.DiscountCouponId > 0) {

                        pay.Paycontent.Add(new IcConsumepayReq.PaycontentItem {
                            Paytype = "6",
                            Paymoney = data.DiscountCouponMoney.ToString(CultureInfo.CurrentCulture).ToDouble(0),
                            Paytradeno = $"t{DateTime.Now.ToString("yyMMddHHmmssffff", CultureInfo.CurrentCulture)}",
                            Payuser = $"{data.DiscountCouponId}"
                        });
                    }
                    var zcard = await _icApiService.GetCardBalance(data.PayCardNO, $"{LoginInfo.Item3}099".ToInt32(0)).ConfigureAwait(false);
                    if (zcard.code == 0) {
                        var Obj = JsonConvert.DeserializeObject<JObject>(zcard.content);
                        var balance = Obj["totalmoney"].ToDecimal(0);
                        if (balance < order.PayCashMoney) {
                            if (cardinfo.CardType == "3")//幸福卡
                            {
                                return new BaseResult<PaymentRsp>(null, -40, "卡内余额不足");

                            }
                            return new BaseResult<PaymentRsp>(null, -39, "卡内余额不足");
                        }
                        if (data.DiscountCouponId > 0 && cardinfo.CardType == "3") {
                            return new BaseResult<PaymentRsp>(null, -41, "优惠券不能与幸福卡同时使用");
                        }
                    } else {
                        return new BaseResult<PaymentRsp>(null, zcard.code, zcard.msg);
                    }
                    payment.PayMethod = data.PayMethod;
                    payment.State = 1;
                    payment.OperationState = 1;
                    payment.PayTime = DateTime.Now;



                    var zmodel = await _icApiService.Icconsumepay(pay).ConfigureAwait(false);
                    if (zmodel.code == 0) {
                        var jobject = JsonConvert.DeserializeObject<JObject>(zmodel.content);
                        if (jobject != null) {
                            if (jobject["invoiceqrcode"] != null) {
                                var invoiceUrl = jobject["invoiceqrcode"].ToString();
                                await _order.UpdateOrderInvoiceUrlByOrderCodeAsync<ICasaMielSession>(payment.BillNO, invoiceUrl).ConfigureAwait(false);
                            }
                        }

                        //var jobject = JsonConvert.DeserializeObject<JObject>(zmodel.content);
                        //var tradeno = jobject["tradeno"].ToString();
                        //payment.OutTradeNo = tradeno;
                        //todo:zhifucg
                        using (var uow = _session.UnitOfWork(IsolationLevel.Serializable)) {
                            order.OrderStatus = (int)OrderStatus.Paid;
                            order.PayMethod = payment.PayMethod;
                            order.PayTime = DateTime.Now;
                            await _order.OrderBaseUPdateAsync(order, uow).ConfigureAwait(true);
                            await _order.UpdateOrderTakeStatus(order.OrderBaseId, 0, "", uow).ConfigureAwait(true);
                            await _paymentService.AddAsync(payment, uow).ConfigureAwait(true);

                            var noticEntity = new NoticeBaseEntity() {
                                RemindTime = DateTime.Now.AddMinutes(3),
                                CreateTime = DateTime.Now,
                                RelationId = order.OrderBaseId,
                                StoreId = order.StoreId,
                                NoticeType = 0
                            };
                            await _notice.AddAsync(noticEntity, uow).ConfigureAwait(true);
                        }
                        var logdata = new UserLog { Url = Request.GetShortUri(), OPInfo = $"蛋糕订单支付,卡号:[{data.CardNO},支付金额{order.PayCashMoney}，订单号：{order.OrderCode}", OPTime = DateTime.Now, UserName = mobile, UserIP = Request.GetUserIp() };
                        await _mediator.Publish(new UserLogNoticeCommand(logdata)).ConfigureAwait(false);

                        payRsp.Payed = true;


                        var cmd3 = new OrderCreateMemberCouponCommand { ActivityId = 6, OrderCode = order.OrderCode };
                        var rsp = await _mediator.Send(cmd3).ConfigureAwait(false);
                        logger.Trace($"OrderCreateMemberCouponCommand:{order.OrderCode},{JsonConvert.SerializeObject(rsp)}");

                        return new BaseResult<PaymentRsp>(payRsp, 0, "");

                    } else {
                        return new BaseResult<PaymentRsp>(null, zmodel.code, zmodel.msg);

                    }
                default:

                    using (var uow = _session.UnitOfWork(IsolationLevel.Serializable)) {
                        order.LastUpdateTime = DateTime.Now;
                        await _order.OrderBaseUPdateAsync(order, uow).ConfigureAwait(true);
                    }
                    var command = new CreatePaymentRequestCommand(payment, data.id, PaymentScenario.CakeStore);
                    var result = await _mediator.Send(command).ConfigureAwait(false);
                    payRsp.Paymentrequest = result.Paymentrequest;
                    payRsp.Payed = result.Payed;
                    return new BaseResult<PaymentRsp>(payRsp, 0, "");
            }
        }


        /// <summary>
        /// Payment the specified data and token.
        /// </summary>
        /// <returns>The payment.</returns>
        /// <param name="data">Data.</param>
        /// <param name="token">Token.</param>
        [HttpPost]
        [Route("[action]")]
        public async Task<BaseResult<PaymentRsp>> PaymentWithCashCoupon([FromBody] OrderPaymentV2Req data, [FromHeader(Name = "u-token")] string token)
        {
            if (data == null) {
                throw new ArgumentNullException(nameof(data));
            }

            var mobile = MemberHelper.GetMobile(token);
            var order = await _order.GetByOrderCodeAsync<ICasaMielSession>(data.OrderCode, mobile).ConfigureAwait(false);
            if (order == null) {
                return new BaseResult<PaymentRsp>(null, -23, "订单不存在");
            }
            var Storeinfo = await _storeService.GetByStoreIdAsync<ICasaMielSession>(order.StoreId).ConfigureAwait(false);
            if (Storeinfo == null) {
                return new BaseResult<PaymentRsp>(null, -23, "订单不存在");
            }
            if (order.OrderStatus != (int)OrderStatus.Create) {
                return new BaseResult<PaymentRsp>(null, -24, "订单状态不是待支付");
            }

            var payRsp = new PaymentRsp {
                OrderCode = order.OrderCode,
                PayMethod = data.PayMethod

            };
            if (order.OrderType == 1) {
                var orderTake = await _storeService.GetOrdeTakeByOrderCodeAsync<ICasaMielSession>(order.OrderBaseId).ConfigureAwait(false);
                if (orderTake == null) {
                    return new BaseResult<PaymentRsp>(null, -26, "提货单据出错");
                }
                if (order.CreateTime.DayOfYear == orderTake.TakeTime.DayOfYear) {
                    if (order.CreateTime.DayOfYear == DateTime.Now.DayOfYear) {
                        if (orderTake.TakeTime <= DateTime.Now) {
                            return new BaseResult<PaymentRsp>(null, -24, "订单状态不是待支付");
                        }
                    }
                } else {
                    if (orderTake.TakeTime.DayOfYear == DateTime.Now.DayOfYear || orderTake.TakeTime.DayOfYear < DateTime.Now.DayOfYear) {
                        return new BaseResult<PaymentRsp>(null, -24, "订单状态不是待支付");
                    }
                }
            }
            for (int i = 0; i < data.DiscountList.Count; i++) {
                if (data.DiscountList[i].DiscountCouponType == 1) {
                    var a = await _icApiService.Geticticket(new GetTicticketReq { Cardno = data.DiscountList[i].CardNo, Pagesize = 200, State = 2, Pageindex = 1 }).ConfigureAwait(false);
                    if (a.code == 0) {
                        var list = JsonConvert.DeserializeObject<TicketItemRoot>(a.content);
                        var ticket = list.Tickets.Where(t => t.Ticketid == data.DiscountList[i].DiscountCouponId).SingleOrDefault();
                        if (ticket != null) {
                            data.DiscountList[i].DiscountCouponMoney = ticket.Je.ToDecimal(0);
                        } else {
                            return new BaseResult<PaymentRsp>(null, -23, "优惠券不可用");

                        }
                    } else {
                        return new BaseResult<PaymentRsp>(null, -23, "优惠券不可用");
                    }
                } else if (data.DiscountList[i].DiscountCouponType == 1) {

                }
            }

            var p_tradeno = $"C{DateTime.Now.ToString("yyMMddHHmmssfff", CultureInfo.CurrentCulture)}";
            var payment = new PaymentRecord { OperationMethod = 2, TradeNo = p_tradeno, Amount = order.PayCashMoney.ToString(CultureInfo.CurrentCulture).ToDouble(0), PayMethod = data.PayMethod, BillNO = order.OrderCode, IcTradeNO = order.IcTradeNO, State = 0, OperationState = 0, CreateTime = DateTime.Now, Mobile = mobile };
            var shopno = "";
            var shopinfo = await _paymentService.GetShopIdAndShopNameByBillNOAsync<ICasaMielSession>(order.OrderCode).ConfigureAwait(false);
            payment.ShopName = shopinfo.Item2;
            payment.ShopId = shopinfo.Item1;

            var cachekey = string.Format(CultureInfo.CurrentCulture, Constant.SHOPNO, _memcachedPrex, payment.ShopId.Value);
            shopno = await _memcachedClient.GetValueAsync<string>(cachekey).ConfigureAwait(false);
            if (string.IsNullOrEmpty(shopno)) {
                var basedata = await _icApiService.BasedataQuery(new BasedataqueryReq { Datatype = 3, Datavalue = $"{payment.ShopId.Value}" }).ConfigureAwait(false);
                if (basedata.code == 0) {
                    var d = JsonConvert.DeserializeObject<JArray>(basedata.content);
                    if (d.Count > 0) {
                        shopno = d[0]["no"].ToString();
                        await _memcachedClient.AddAsync(cachekey, shopno, 72000).ConfigureAwait(false);
                    }
                }
            }
            payment.ShopNO = shopno;


            if (order.PayCashMoney == 0) {
                var pay = new IcConsumepayReq {
                    Shopid = Storeinfo.RelationId,
                    Tradeno = order.IcTradeNO,
                    Phoneno = mobile
                };
                pay.Paycontent = new List<IcConsumepayReq.PaycontentItem>();
                data.DiscountList.ForEach((Action<OrderDiscountReq>)(x => {
                    var _paytype = "5";
                    if (x.DiscountCouponType == 1) { _paytype = "6"; }

                    pay.Paycontent.Add(new IcConsumepayReq.PaycontentItem {
                        Paytype = _paytype,
                        Paymoney = x.DiscountCouponMoney.ToString(CultureInfo.CurrentCulture).ToDouble(0),
                        Paytradeno = $"t{DateTime.Now.ToString("yyMMddHHmmssffff", CultureInfo.CurrentCulture)}",
                        Payuser = $"{x.DiscountCouponId}"
                    });
                }));
                //if (data.DiscountCouponId > 0)
                //{
                //    pay.paycontent.Add(new IcConsumepayReq.Paycontent
                //    {
                //        paytype = "6",
                //        paymoney = data.DiscountCouponMoney.ToString().ToDouble(0),
                //        paytradeno = $"t{DateTime.Now.ToString("yyMMddHHmmssffff")}",
                //        payuser = $"{data.DiscountCouponId}"
                //    });
                //}


                var zmodel = await _icApiService.Icconsumepay(pay).ConfigureAwait(false);
                if (zmodel.code == 0) {
                    payment.PayMethod = data.PayMethod;
                    payment.PayTime = DateTime.Now;
                    payment.State = 1;
                    payment.OperationState = 1;
                    using (var uow = _session.UnitOfWork(IsolationLevel.Serializable)) {
                        order.OrderStatus = (int)OrderStatus.Paid;
                        order.PayTime = DateTime.Now;
                        await _order.OrderBaseUPdateAsync(order, uow).ConfigureAwait(true);
                        await _order.UpdateOrderTakeStatus(order.OrderBaseId, 0, "", uow).ConfigureAwait(true);
                        payment.State = 1;
                        payment.OperationState = 1;
                        payment.PayTime = DateTime.Now;
                        await _paymentService.AddAsync(payment, uow).ConfigureAwait(true);
                        var noticEntity = new NoticeBaseEntity() {
                            RemindTime = DateTime.Now.AddMinutes(-3),
                            CreateTime = DateTime.Now,
                            RelationId = order.OrderBaseId,
                            StoreId = order.StoreId,
                            NoticeType = 0
                        };
                        await _notice.AddAsync(noticEntity, uow).ConfigureAwait(true);

                    }
                    // return new JsonResult(new { code = 0, content = new { paymentrequest = "", ordercode = order.OrderCode, payMethod = payment.PayMethod.ToString(), payed = true } });
                    payRsp.Payed = true;

                    return new BaseResult<PaymentRsp>(payRsp, 0, "");
                }
                return new BaseResult<PaymentRsp>(null, zmodel.code, zmodel.msg);
            }

            switch (data.PayMethod) {
                case 3:
                    if (string.IsNullOrEmpty(data.PayCardNO)) {
                        return new BaseResult<PaymentRsp>(null, 999, "卡号不能为空");
                    }
                    var cardinfo = await _memberCardService.FindAsync<ICasaMielSession>(data.PayCardNO, mobile).ConfigureAwait(false);
                    if (cardinfo == null) {
                        return new BaseResult<PaymentRsp>(null, 999, "卡号有误");
                    }

                    var pay = new IcConsumepayReq {
                        Cardno = data.PayCardNO,
                        Shopid = Storeinfo.RelationId,
                        Tradeno = order.IcTradeNO,
                        Createinvoice = true
                    };
                    pay.Paycontent = new List<IcConsumepayReq.PaycontentItem>
                    {
                        new IcConsumepayReq.PaycontentItem
                        {
                            Paytype = "3",
                            Paymoney = order.PayCashMoney.ToString(CultureInfo.CurrentCulture).ToDouble(0),
                            Paytradeno = $"c{DateTime.Now.ToString("yyMMddHHmmssffff",CultureInfo.CurrentCulture)}"
                        }
                    };
                    data.DiscountList.ForEach((Action<OrderDiscountReq>)(x => {
                        var _paytype = "5";
                        if (x.DiscountCouponType == 1) { _paytype = "6"; }

                        pay.Paycontent.Add(new IcConsumepayReq.PaycontentItem {
                            Paytype = _paytype,
                            Paymoney = x.DiscountCouponMoney.ToString(CultureInfo.CurrentCulture).ToDouble(0),
                            Paytradeno = $"t{DateTime.Now.ToString("yyMMddHHmmssffff", CultureInfo.CurrentCulture)}",
                            Payuser = $"{x.DiscountCouponId}"
                        });
                    }));
                    var zcard = await _icApiService.GetCardBalance(data.PayCardNO, $"{LoginInfo.Item3}099".ToInt32(0)).ConfigureAwait(false);
                    if (zcard.code == 0) {
                        var Obj = JsonConvert.DeserializeObject<JObject>(zcard.content);
                        var balance = Obj["totalmoney"].ToDecimal(0);
                        if (balance < order.PayCashMoney) {
                            if (cardinfo.CardType == "3")//幸福卡
                            {
                                return new BaseResult<PaymentRsp>(null, -40, "卡内余额不足");

                            }
                            return new BaseResult<PaymentRsp>(null, -39, "卡内余额不足");
                        }
                        if ((data.PayMethod == 3) && (cardinfo.CardType == "3")) {
                            return new BaseResult<PaymentRsp>(null, -41, "优惠券不能与幸福卡同时使用");
                        }
                    } else {
                        return new BaseResult<PaymentRsp>(null, zcard.code, zcard.msg);
                    }
                    payment.PayMethod = 3;
                    payment.State = 1;
                    payment.OperationState = 1;
                    payment.PayTime = DateTime.Now;



                    var zmodel = await _icApiService.Icconsumepay(pay).ConfigureAwait(false);
                    if (zmodel.code == 0) {
                        var jobject = JsonConvert.DeserializeObject<JObject>(zmodel.content);
                        if (jobject != null && jobject["invoiceqrcode"] != null) {
                            var invoiceUrl = jobject["invoiceqrcode"].ToString();
                            await _order.UpdateOrderInvoiceUrlByOrderCodeAsync<ICasaMielSession>(payment.BillNO, invoiceUrl).ConfigureAwait(false);
                        } else {
                            logger.Error($"Invoideurl:{zmodel.content}");
                        }
                        //var jobject = JsonConvert.DeserializeObject<JObject>(zmodel.content);
                        //var tradeno = jobject["tradeno"].ToString();
                        //payment.OutTradeNo = tradeno;
                        //todo:zhifucg
                        using (var uow = _session.UnitOfWork(IsolationLevel.Serializable)) {
                            order.OrderStatus = (int)OrderStatus.Paid;
                            order.PayMethod = payment.PayMethod;
                            order.PayTime = DateTime.Now;
                            await _order.OrderBaseUPdateAsync(order, uow).ConfigureAwait(true);
                            await _order.UpdateOrderTakeStatus(order.OrderBaseId, 0, "", uow).ConfigureAwait(true);
                            await _paymentService.AddAsync(payment, uow).ConfigureAwait(true);

                            var noticEntity = new NoticeBaseEntity() {
                                RemindTime = DateTime.Now.AddMinutes(3),
                                CreateTime = DateTime.Now,
                                RelationId = order.OrderBaseId,
                                StoreId = order.StoreId,
                                NoticeType = 0
                            };
                            await _notice.AddAsync(noticEntity, uow).ConfigureAwait(true);
                        }
                        var logdata = new UserLog { Url = Request.GetShortUri(), OPInfo = $"蛋糕订单支付,卡号:[{data.PayCardNO},支付金额{order.PayCashMoney}，订单号：{order.OrderCode}", OPTime = DateTime.Now, UserName = mobile, UserIP = Request.GetUserIp() };

                        await _mediator.Publish(new UserLogNoticeCommand(logdata)).ConfigureAwait(false);
                        
                             payRsp.Payed = true;
                        return new BaseResult<PaymentRsp>(payRsp, 0, "");


                    } else {
                        return new BaseResult<PaymentRsp>(null, zmodel.code, zmodel.msg);

                    }
                default:
                    var command = new CreatePaymentRequestCommand(payment, data.id, PaymentScenario.CakeStore);
                    var result = await _mediator.Send(command).ConfigureAwait(false);
                    payRsp.Paymentrequest = result.Paymentrequest;
                    payRsp.Payed = result.Payed;
                    return new BaseResult<PaymentRsp>(payRsp, 0, "");
            }
        }

    }
}
